#pragma once

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QMap>

#include "KeyInfo.h"
#include "Contact.h"
#include "Group.h"
#include "SymmetricKeyInfo.h"

#include <vector>

namespace kryptos { namespace database {

class KeyDAO;

class DatabaseManager
{
  public:

    virtual ~DatabaseManager();

    static DatabaseManager& manager();

    void openKeyring();
    void openGroups ();

    void addKeyPair  (const kryptos::entities::KeyInfo& info, const QByteArray& privatePart, const QByteArray& publicPart);
    void addPublicKey(const kryptos::entities::KeyInfo& info, const QByteArray& publicPart);

    kryptos::entities::KeyInfoList allKeys();
    kryptos::entities::KeyInfoList keysWithPublicAndPrivateData();

    bool   hasKeyWithNameAndEmail(const QString& name, const QString& email);
    bool   hasKeyWithEmail       (const QString& email);
    bool   hasKeyWithId          (const QString& id);
    KeyDAO getKey                (const QString& idOrEmail);

    void   addGroup         (const kryptos::entities::Group& group);
    void   addContactToGroup(const kryptos::entities::Contact& contact, const kryptos::entities::Group& group);
    bool   hasGroup         (const std::string& name);

    kryptos::entities::GroupList   allGroups();
    kryptos::entities::GroupList   allGroupsWithoutKeyFiles();
    kryptos::entities::GroupList   allGroupsWithKeyFiles();

    kryptos::entities::Group       findGroup(const std::string& name);

    kryptos::entities::SymmetricKeyInfoList allSymmetricKeys();
    kryptos::entities::SymmetricKeyInfoList getSymmetricKeysAssignedToKeyID(const std::string& keyid);

private:
    DatabaseManager();

    QSqlQuery* searchKey(QMap<QString, QString> params=QMap<QString, QString>());

    QSqlDatabase m_keyRingDB, m_groupsDB;
};

class KeyDAO
{
  public:
    KeyDAO(){}
    KeyDAO(const kryptos::entities::KeyInfo& info, const QByteArray& publicPart)
    {
        m_info = info;
        m_publicPart.append(publicPart);
    }

    KeyDAO(const kryptos::entities::KeyInfo& info, const QByteArray& privatePart, const QByteArray& publicPart)
    {
        m_info = info;
        m_privatePart.append(privatePart);
        m_publicPart.append(publicPart);
    }

    virtual ~KeyDAO(){}

    kryptos::entities::KeyInfo keyInfo() { return m_info;}

    QByteArray privatePart() { return m_privatePart;}
    QByteArray publicPart () { return m_publicPart;}

    std::vector<char> privatePartToStdVector() { return std::vector<char>(m_privatePart.begin(), m_privatePart.end());}
    std::vector<char> publicPartStdVector   () { return std::vector<char>(m_publicPart.begin(), m_publicPart.end());}

private:

    kryptos::entities::KeyInfo    m_info;
    QByteArray m_privatePart, m_publicPart;
};

}}

